home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 333_01 / awktab.c < prev   
C/C++ Source or Header  |  1989-04-21  |  47KB  |  1,671 lines

  1. /*
  2.  * Created by CSD YACC (IBM PC) from "AWKTAB.Y" */
  3.  
  4. /* #line 31 "AWKTAB.Y" */
  5. #define YYDEBUG 12
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <stdarg.h>
  10. #include <string.h>
  11. #include "awk.h"
  12.  
  13. STATIC int      NEAR PASCAL     yylex(void);
  14. STATIC int      NEAR PASCAL     parse_escape(char **string_ptr);
  15.  
  16.  
  17. /* The following variable is used for a very sickening thing.  The awk      */
  18. /* language uses white space as the string concatenation operator, but      */
  19. /* having a white space token that would have to appear everywhere in all */
  20. /* the grammar rules would be unbearable.  It turns out we can return      */
  21. /* CONCAT_OP exactly when there really is one, just from knowing what      */
  22. /* kinds of other tokens it can appear between (namely, constants,      */
  23. /* variables, or close parentheses).  This is because concatenation has   */
  24. /* the lowest priority of all operators.  want_concat_token is used to      */
  25. /* remember that something that could be the left side of a concat has      */
  26. /* just been returned.    If anyone knows a cleaner way to do this (don't   */
  27. /* look at the Un*x code to find one, though), please suggest it.      */
  28.  
  29. static int          want_concat_token;
  30.  
  31. /* Two more horrible kludges.  The same comment applies to these two too  */
  32.  
  33. static int          want_regexp     = 0; /* lexical scanning kludge   */
  34.  
  35. int              lineno = 1;         /* JF for error msgs      */
  36.  
  37. /* During parsing of a gAWK program, the pointer to the next character      */
  38. /* is in this variable.                           */
  39.  
  40. char             *lexptr;
  41. char             *lexptr_begin;
  42.  
  43.  
  44. /* #line 71 "AWKTAB.Y" */
  45. typedef union 
  46. {
  47.     long      lval;
  48.     AWKNUM      fval;
  49.     NODE     *nodeval;
  50.     int       nodetypeval;
  51.     char     *sval;
  52.     NODE    *(PASCAL *ptrval)(NODE *);
  53. } YYSTYPE;
  54. #define NAME 257
  55. #define REGEXP 258
  56. #define YSTRING 259
  57. #define ERROR 260
  58. #define INCDEC 261
  59. #define NUMBER 262
  60. #define ASSIGNOP 263
  61. #define MATCHOP 264
  62. #define NEWLINE 265
  63. #define CONCAT_OP 266
  64. #define LEX_BEGIN 267
  65. #define LEX_END 268
  66. #define LEX_IF 269
  67. #define LEX_ELSE 270
  68. #define LEX_WHILE 271
  69. #define LEX_FOR 272
  70. #define LEX_BREAK 273
  71. #define LEX_CONTINUE 274
  72. #define LEX_DELETE 275
  73. #define LEX_PRINT 276
  74. #define LEX_PRINTF 277
  75. #define LEX_NEXT 278
  76. #define LEX_EXIT 279
  77. #define RELOP_EQ 280
  78. #define RELOP_GEQ 281
  79. #define RELOP_LEQ 282
  80. #define RELOP_NEQ 283
  81. #define REDIR_APPEND 284
  82. #define LEX_IN 285
  83. #define LEX_AND 286
  84. #define LEX_OR 287
  85. #define INCREMENT 288
  86. #define DECREMENT 289
  87. #define LEX_BUILTIN 290
  88. #define LEX_MATCH_FUNC 291
  89. #define LEX_SUB_FUNC 292
  90. #define LEX_SPLIT_FUNC 293
  91. #define LEX_GETLINE 294
  92. #define UNARY 295
  93. #define yyclearin yychar = -1
  94. #define yyerrok yyerrflag = 0
  95. #ifndef YYMAXDEPTH
  96. #define YYMAXDEPTH 150
  97. #endif
  98. YYSTYPE yylval;         /*CSD & DECUS LEX */
  99. YYSTYPE yyval;          /*CSD & DECUS LEX */
  100. #define YYERRCODE 256
  101.  
  102. /* #line 713 "AWKTAB.Y" */
  103.  
  104.  
  105.  
  106. struct token
  107. {
  108.     char      *operator;
  109.     int        value;
  110.     int        class;
  111.     NODE     *(PASCAL *ptr)(NODE *);
  112. };
  113.  
  114.  
  115.  
  116. /* Tokentab is sorted ascii ascending order, so it can be binary searched. */
  117. /* DO NOT enter table entries out of order lest search can't find them.    */
  118.  
  119. static struct token tokentab[] =
  120. {
  121.     { "BEGIN",       NODE_ILLEGAL,       LEX_BEGIN,       NULL        },
  122.     { "END",       NODE_ILLEGAL,       LEX_END,       NULL        },
  123.     { "atan2",       NODE_BUILTIN,       LEX_BUILTIN,    do_atan2    },
  124. #ifndef FAST
  125.     { "bp",       NODE_BUILTIN,       LEX_BUILTIN,    do_bp       },
  126. #endif
  127.     { "break",       NODE_K_BREAK,       LEX_BREAK,       NULL        },
  128.     { "close",       NODE_BUILTIN,       LEX_BUILTIN,    do_close    },
  129.     { "continue",  NODE_K_CONTINUE,       LEX_CONTINUE,   NULL        },
  130.     { "cos",       NODE_BUILTIN,       LEX_BUILTIN,    do_cos      },
  131.     { "delete",    NODE_K_DELETE,       LEX_DELETE,       NULL        },
  132.     { "else",       NODE_ILLEGAL,       LEX_ELSE,       NULL        },
  133.     { "exit",       NODE_K_EXIT,        LEX_EXIT,       NULL        },
  134.     { "exp",       NODE_BUILTIN,       LEX_BUILTIN,    do_exp      },
  135.     { "for",       NODE_K_FOR,           LEX_FOR,       NULL        },
  136.     { "getline",   NODE_BUILTIN,       LEX_GETLINE,    do_getline  },
  137.     { "gsub",       NODE_BUILTIN,       LEX_SUB_FUNC,   do_gsub     },
  138.     { "if",       NODE_K_IF,           LEX_IF,       NULL        },
  139.     { "in",       NODE_ILLEGAL,       LEX_IN,       NULL        },
  140.     { "index",       NODE_BUILTIN,       LEX_BUILTIN,    do_index    },
  141.     { "int",       NODE_BUILTIN,       LEX_BUILTIN,    do_int      },
  142.     { "length",    NODE_BUILTIN,       LEX_BUILTIN,    do_length   },
  143.     { "log",       NODE_BUILTIN,       LEX_BUILTIN,    do_log      },
  144.     { "lower",       NODE_BUILTIN,       LEX_BUILTIN,    do_lower    },
  145.     { "match",       NODE_BUILTIN,       LEX_MATCH_FUNC, do_match    },
  146.     { "next",       NODE_K_NEXT,        LEX_NEXT,       NULL        },
  147.     { "print",       NODE_K_PRINT,       LEX_PRINT,       NULL        },
  148.     { "printf",    NODE_K_PRINTF,       LEX_PRINTF,       NULL        },
  149. #ifndef FAST
  150.     { "prvars",    NODE_BUILTIN,       LEX_BUILTIN,    do_prvars   },
  151. #endif
  152.     { "rand",       NODE_BUILTIN,       LEX_BUILTIN,    do_rand     },
  153.     { "reverse",   NODE_BUILTIN,       LEX_BUILTIN,    do_reverse  },
  154.     { "sin",       NODE_BUILTIN,       LEX_BUILTIN,    do_sin      },
  155.     { "split",       NODE_BUILTIN,       LEX_SPLIT_FUNC, do_split    },
  156.     { "sprintf",   NODE_BUILTIN,       LEX_BUILTIN,    do_sprintf  },
  157.     { "sqrt",       NODE_BUILTIN,       LEX_BUILTIN,    do_sqrt     },
  158.     { "srand",       NODE_BUILTIN,       LEX_BUILTIN,    do_srand    },
  159.     { "sub",       NODE_BUILTIN,       LEX_SUB_FUNC,   do_sub      },
  160.     { "substr",    NODE_BUILTIN,       LEX_BUILTIN,    do_substr   },
  161.     { "system",    NODE_BUILTIN,       LEX_BUILTIN,    do_system   },
  162.     { "upper",       NODE_BUILTIN,       LEX_BUILTIN,    do_upper    },
  163.     { "while",       NODE_K_WHILE,       LEX_WHILE,       NULL        }
  164. };
  165.  
  166. /* Read one token, getting characters through lexptr.  */
  167.  
  168. STATIC int NEAR PASCAL yylex(void)
  169. {
  170.     register int         c;
  171.     register int         namelen;
  172.     register char        *tokstart;
  173.     static   int         last_tok_1  = 0;
  174.     static   int         last_tok_2  = 0;
  175.     static   int         did_newline = 0; /* JF the grammar insists that */
  176.                           /* actions end with newlines.  */
  177.     auto     int         do_concat;
  178.     auto     int         seen_e = 0;      /* These are for numbers         */
  179.     auto     int         seen_point = 0;
  180.     auto     int         next_tab;
  181.  
  182. retry:
  183.     if(!lexptr)
  184.     return(0);
  185.  
  186.     if (want_regexp)
  187.     {
  188.     /* there is a potential bug if a regexp is followed by an equal     */
  189.     /* sign: "/foo/=bar" would result in assign_quotient being returned */
  190.     /* as the next token.  Nothing is done about it since it is not     */
  191.     /* valid awk, but maybe something should be done anyway.        */
  192.     want_regexp = 0;
  193.  
  194.     tokstart = lexptr;
  195.     while (c = *lexptr++)
  196.     {
  197.         switch (c)
  198.         {
  199.         case '\\':
  200.             if (*lexptr++ == EOS)
  201.             {
  202.             yyerror ("unterminated regexp ends with \\");
  203.             return(ERROR);
  204.             }
  205.             break;
  206.         case '/':          /* end of the regexp */
  207.             lexptr--;
  208.             yylval.sval = tokstart;
  209.             return(REGEXP);
  210.         case '\n':
  211.         case EOS:
  212.             yyerror("unterminated regexp");
  213.             return(ERROR);
  214.         }
  215.     }
  216.     }
  217.     do_concat          = want_concat_token;
  218.     want_concat_token = 0;
  219.  
  220.     if (*lexptr == EOS)
  221.     {
  222.     lexptr = NULL;
  223.     return(NEWLINE);
  224.     }
  225.  
  226.     /* if lexptr is at white space between two terminal tokens or parens,  */
  227.     /* it is a concatenation operator.                       */
  228.     if (do_concat && (*lexptr == ' ' || *lexptr == '\t'))
  229.     {
  230.     while (*lexptr == ' ' || *lexptr == '\t')
  231.         lexptr++;
  232.     if (isalnum(*lexptr) || *lexptr == '\"' || *lexptr == '('
  233.                  || *lexptr == '.'    || *lexptr == '$')
  234.         return(CONCAT_OP);
  235.     }
  236.  
  237.     while (*lexptr == ' ' || *lexptr == '\t')
  238.     lexptr++;
  239.  
  240.     tokstart   = lexptr;          /* JF */
  241.     last_tok_1 = last_tok_2;
  242.     last_tok_2 = *lexptr;
  243.  
  244.     switch (c = *lexptr++)
  245.     {
  246.     case 0:
  247.         return(0);
  248.     case '\n':
  249.         ++lineno;
  250.         if (',' == last_tok_1)     /* BW: allow lines to be continued */
  251.         goto retry;         /*    at a comma            */
  252.         return(NEWLINE);
  253.     case '#':              /* it's a comment */
  254.         while (*lexptr != '\n